home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / NDK / NDK_3.5 / Tutorials / Printer / Deutsch / Treiber.dok < prev   
Encoding:
Text File  |  1999-10-11  |  22.6 KB  |  545 lines

  1. printer.device V44 (OS 3.5)
  2.  
  3. Treiber für das neue printer.device.
  4.  
  5. Das neue printer.device bietet für Druckertreiber vielfältige neue 
  6. Möglichkeiten und räumt mit einigen Problemen des alten printer.device
  7. auf.
  8.  
  9. Änderungen:
  10.  
  11. 1. Der Treiber läuft jetzt immer in einem DOS Prozess. Der Stack ist
  12. dabei mindestens 8 KB groß.
  13.  
  14. 2. Die Funktionen PWrite und PBothReady sind nun sinnvoll in jeder
  15. Situation benutzbar, auch in DoSpecial.
  16.  
  17. 8. Treiber können mit der neuen Funktion PRead von der I/O Schnittstelle
  18. lesen.
  19.  
  20. 3. Durch eine Erweiterung der Kommandotabelle kann die Vertauschung von
  21. Ausgaben aus DoSpecial mit PWrite und Ausgaben des printer.device verhindert 
  22. werden.
  23.  
  24. 4. Treiber können aus allen notwendigen Situationen Fehlermeldungen 
  25. zurückgeben (auch aus DoSpecial) und eigene Fehlercodes benutzen.
  26.  
  27. 5. Treiber formatieren und lokalisieren die Fehlercodes zur Ausgabe selbst.
  28.  
  29. 5. Treiber können die Farbkonvertierung, -korrektur, Dithering usw. selbst
  30. durchführen ohne Seiteneffekte mit dem printer.device befürchten oder den 
  31. sehr aufwendigen Weg des PDERR_TOOKCONTROL nehmen zu müssen.
  32.  
  33. 6. Die Skalierung übernimmt das printer.device komplett oder auf Wunsch
  34. überhaupt nicht.
  35.  
  36. 7. Treiber können eine eigene Struktur für die Farben benutzen. Dadurch sind
  37. auch Standardimplementationen für Farbraumkonvertierung etc einsetzbar.
  38.  
  39. 9. Treiber können auf die Darstellung der Druckerpreferences Einfluß nehmen
  40. um diese ihrer Intepretation anzupassen.
  41.  
  42. 10. Treiber können eigenen Druckereinstellungen verwalten und einen eigen
  43. Druckerdialog besitzen.
  44.  
  45. 11. Treiber können neue Informationen an die Applikationen zurückgeben um
  46. den Ausdruck zu verbessern.
  47.  
  48.  
  49. Umsetzung eines alten Treibers in einen neuen Treiber
  50.  
  51. 1. Treibererkennung setzen
  52.  
  53. Ein neuer Treiber muß eine Versionsnummer 44 oder höher haben und außerdem das
  54. Bit PPCF_EXTENDED in ped_PrinterClass gesetzt haben. Dann muß die Struktur
  55. PrinterExtendedData um die neuen Felder ergänzt werden:
  56.  
  57. ped_TagList ist ein Pointer auf eine Tagliste, die im wesentlichen die
  58. erweiterte Treiberdefinition enthält.
  59.  
  60. ped_DoPreferences ist ein Funktionspointer. Die Funktion wird aufgerufen um
  61. die verschiedenen Kommandos für treiberspezifische Einstellungen zu verwalten.
  62.  
  63. ped_CallErrHook ist ein Funktionspointer. Die Funktion wird aufgerufen um
  64. einen treibereigenen Fehlercode zu formatieren und mit Hilfe eines Hooks
  65. auszugeben.
  66.  
  67. Die Tags von ped_TagList im einzelnen:
  68.  
  69. PRTA_8BitGuns: Hat dieses Tag den Wert TRUE, so wird jede Farbe in 256
  70. Intensitäten berechnet. Damit sind bis zu 16 Millionen Farben möglich
  71. (die jedoch kaum ein Drucker komplett ausdrucken kann). Ist dieses Tag nicht
  72. vorhanden oder der Wert FALSE, so wird wie bislang mit 16 Intensitäten pro 
  73. Farbe gearbeitet. Neue Treiber sollten auf jeden Fall dieses Tag setzen.
  74.  
  75. PRTA_ConvertSource: Hat dieses Tag den Wert TRUE, so überläßt das
  76. printer.device die Umrechnung der Farben aus dem sRGB Farbraum in den
  77. druckerspezifischen Farbraum (häufig YMCK) dem Treiber. Die Konvertierung
  78. erfolgt dann durch Aufruf der Funktion ped_Render mit Status 8. Der
  79. 1. Parameter ist ein Pointer auf 24 Bit BGR Werte (man beachte die 
  80. ungewöhnliche Reihenfolge BGR aus Kompatibilitätsgründen), der 2. Parameter
  81. enthält die Anzahl der Pixel im Array, der 3. Parameter ist 0, falls das
  82. Array eine Colormap ist oder 1, falls das Array eine Pixelzeile ist. Die 
  83. Größe jeden Eintrags ist entweder gegeben durch PRTA_ColorSize oder
  84. sizeof(union colorEntry).
  85.  
  86. PRTA_FloydDithering: Hat dieses Tag den Wert TRUE, so überläßt das
  87. printer.device auch das Floyd-Dithering dem Treiber (oder welche Dithermethode
  88. auch immer benutzt wird). Ist das Tag PRTA_8BitGuns TRUE, so wird implizit
  89. auch dieses Tag auf TRUE gesetzt, d.h. im Normalfall ist der Treiber immer
  90. auch für die dritte Dithermethode selbst zuständig.
  91.  
  92. PRTA_AntiAlias: Hat dieses Tag den Wert TRUE, so überläßt das printer.device
  93. das Smoothing dem Treiber. Der Treiber muß das Smoothing dann auch im
  94. render 1 Aufruf durchführen.
  95.  
  96. PRTA_ColorCorrection: Hat dieses Tag den Wert TRUE, so überläßt das 
  97. printer.device die Farbkorrektur dem Treiber. Da die Farbkorrektur des
  98. printer.device nur sehr rudimentär ist und kaum den verschiednen Ansprüchen
  99. der modernen Drucker gerecht wird, empfiehlt es sich dringend, die 
  100. Farbkorrektur im Treiber durchzuführen. Die Farbkorrektur erfolgt durch
  101. Aufruf der ped_Render Funktion mit Status 9. Der erste Parameter ist ein
  102. pointer auf ein Farbarray, der zweite Parameter die Anahl der Elemente im
  103. Array und der dritte Parameter ist 0 für eine Colormap oder 1 für eine
  104. Pixelzeile.
  105.  
  106. PRTA_NoIO: Hat dieses Tag den Wert TRUE, so wird kein I/O Device geöffnet. Der
  107. Treiber darf dann nicht PWrite, PBothReady oder PRead aufrufen. Die Ausgabe
  108. muß direkt durch den Treiber ausgeführt werden. Faxtreiber oder Treiber, die
  109. die Ausgabe in eine Datei schreiben belegen dadurch nicht mehr unnötig I/O
  110. Resourcen.
  111.  
  112. PRTA_NewColor: Hat dieses Tag den Wert TRUE, so interpretiert das 
  113. printer.device die Farben nach der Konvertierung nicht mehr. Dieses Tag
  114. impliziert die Tags PRTA_ConvertSource, PRTA_FloydDithering, PRTA_AntiAlias
  115. und PRTA_ColorCorrection alle mit dem Wert TRUE.
  116.  
  117. PRTA_ColorSize: Der Wert dieses Tags gibt die Größe einer Farbe bzw. eines
  118. Pixels an. Der Standardwert ist sizeof(union ColorEntry). Mit Hilfe dieses
  119. Wertes kann der Treiber auch mehr Informationen in der Farbe speichern und
  120. aufwendigere Farbräume unterstützen. Hat der Treiber nicht das Tag 
  121. PRTA_NewColor gesetzt und verwendet einen der Algorithmen des printer.device
  122. für Konvertierung, Korrektur, oder Anti-Alias, so wird jeder Pixel wie ein
  123. union ColorEntry intepretiert, auch wenn als Gesamtgröße eines Pixels ein
  124. größerer Wert benutzt wird. In den meisten Fällen wird man also eine von
  125. union colorEntry abweichende Farbstruktur mit dem Tag PRTA_NewColor
  126. kombinieren müssen.
  127.  
  128. PRTA_NoScaling: Wenn ein Treiber die Skalierung der Rohdaten durch das
  129. printer.device unterbinden möchte, so kann er das mit diesem Tag tun.
  130. Allerdings wird die Skalierung immer noch berechnet, d.h. die Anzahl der
  131. Druckspalten und -zeilen im Renderfall 1 entspricht immer noch den
  132. skalierten Werten. Die Größe der Rohdaten kann man aus den Feldern
  133. PrtInfo.pi_width und pi_height entnehmen. Dieses Tag impliziert
  134. automatisch auch die Tags PRTA_FloydDithering und PRTA_AntiAlias, da diese
  135. Algorithmen nur auf den fertig skalierten Daten arbeiten können.
  136.  
  137. PRTA_DitherNames: Der Wert dieses Tags ist ein Array mit 3 Strings, Namen
  138. für die Ditheringmethoden PD_ORDERED, PD_HALFTONE und PD_FLOYD. Benutzt ein 
  139. Treiber andere Dithermethoden als diese, so soll er dieses Tag verwenden, um 
  140. die wirklichen Dithermethoden zu bezeichnen.
  141.  
  142. PRTA_ShadingNames: Der Wert dieses Tags ist ein Array mit 4 Strings, Namen
  143. für die Shadingvarianten PS_BW, PS_GREYSCALE, PS_COLOR und PS_GREY_SCALE2.
  144. Die beiden letzten Strings sind gegenüber ihrer Reihenfolge im Printer
  145. Einsteller vertauscht! Benutzt ein Treiber andere Shadingmethoden als die
  146. üblichen (z.B. eine spezielle Variante für Grauwerte im Fall von PS_COLOR
  147. für Schwarz/Weiß Drucker), so soll er dieses Tag verwenden, um die
  148. wirklichen Dithermethoden zu bezeichnen. Die Methode PS_GREY_SCALE2 wird
  149. allerdings intern im printer.device als Sonderfall für den Graustufenmonitor
  150. A2024 benutzt, daher macht eine Ersetzung dieser Methode wenig Sinn.
  151.  
  152. PRTA_ColorCorrect: Wenn ein Treiber mit den Einstellungen der Farbkorrektur
  153. für die einzelnen Farbkanäle Rot, Grün und Blau nichts anzufangen weiß, so
  154. soll er dieses Tag auf FALSE setzen, damit die Häkchen in der Oberfläche
  155. gesperrt werden.
  156.  
  157. PRTA_DensityInfo: Treiber, die über die Dichteeinstellung weitere 
  158. Veränderungen am Ausdruck vornehmen (z.B. Tintenmenge) können mit diesem
  159. Tag Benutzerinformationen zu jeder Dichte angeben. Der Wert dieses Tags ist
  160. ein Array mit 8 Strings. Der erste String wird derzeit ignoriert und muß
  161. NULL sein, die anderen 7 Strings entsprechen den Dichten 1 bis 7 und werden
  162. vom Printer Einsteller entsprechend angezeigt.
  163.  
  164. PRTA_LeftBorder, PRTA_TopBorder: Die meisten Drucker haben kleine
  165. Papierränder. Der linke und der obere Rand auf dem Papier den der Drucker
  166. nicht bedrucken kann wird mit diesen Tags in tausendstel inch angegeben. Der
  167. rechte und untere Rand wird entsprechend durch die bedruckbare Fläche
  168. festgelegt. Programme könen die Rändergrößen und Größe der bedruckbaren Fläche
  169. benutzen, um den Ausdruck exakt auf dem Papier zu positionieren.
  170.  
  171. PRTA_MixBWColor: Druckt eine Applikation in Streifen, so kann sie die
  172. Druckgeschwindigkeit wesentlich steigern, wenn Streifen in denen nur
  173. schwarze Graphik/Text auf weißem Papier vorkommt in Schwarz/Weiß druckt;
  174. Streifen mit farbiger Graphik entsprechend in Graustufen oder Farbe. Manche
  175. Drucker benutzen jedoch für Schwarz/Weiß eine andere Tintenpatrone als für
  176. Farbe oder benutzen im Schwarz/Weiß Modus schwarze Tinte und mischen im
  177. Farbmodus Schwarz aus Gelb, Magenta und Cyan. In diesen beiden Fällen ist
  178. eine Optimierung durch die Applikation unerwünscht. Ist dieses Tag FALSE,
  179. so sollte eine Applikation die Optimierung unterlassen.
  180.  
  181. PRTA_Preferences: Wenn der Treiber eigene Einstellungen benutzt und diese
  182. über den Treiber auch verändert werden können, so zeigt dieses Tag es mit 
  183. einem Wert TRUE an. Eine Applikation wird dann einen Knopf "Optionen..."
  184. freigeben, mit dem der Benutzer das Fenster für die Treibereinstellungen
  185. öffnen und editieren kann. Dazu wird der neue Befehl PRD_EDITPREFS verwendet.
  186.  
  187.  
  188. 2. Algorithmen anpassen
  189.  
  190. Die Transfer-Funktion
  191.  
  192. Die Transfer() Funktion des Treibers, die die Umsetzung der Pixel in den 
  193. Druckerpuffer übernimmt, muß nicht mehr skalieren. Bislang war der Sonderfall
  194. der X-Streckung den Treibern überlassen. Dies übernimmt nun immer das
  195. printer.device, das Skalierungsfeld pi_ScaleX enthält nur noch Einsen, die
  196. Schleife, um einen X-Wert entsprechend oft zu benutzen, kann aus der
  197. Funktion entfernt werden.
  198.  
  199. Neue Treiber sollten das Tag PRTA_8BitGuns gesetzt haben und Drucke mit 256
  200. Intensitäten pro Farbkanal unterstützen. Normalerweise muß da nicht viel getan
  201. werden, die typische Transferfunktion arbeitet mit 8 bit genauso wie mit 4.
  202.  
  203. Zwei Dinge sind dabei jedoch meistens zu beachten: Der Thresholdwert 
  204. pi_Threshold ist schon auf 256 Intensitäten gestreckt. Viele Treiber 
  205. invertieren den Wert vor der Benutzung, das muß dann im richtigen Wertebereich
  206. geschehen.
  207.  
  208. Die Dithermatrizen pi_dmatrix entsprechen nach wie vor den Dithermethoden
  209. Ordered und Halftone mit einer Rastergröße 4x4. Wenn man diese Matrizen 
  210. benutzt, so erhält man nur maximal 16 Intensitäten pro Farbkanal im Ausdruck
  211. und damit nur ein wenig verbessertes Bild gegenüber den alten Treibern. In
  212. Äbhängigkeit von der Druckauflösung sollten verschiedene Matrizen benutzt
  213. werden, z.B. 8x8. Im Falle des dritten Ditheralgorithmus Floyd-Steinberg
  214. enthält die Matrix pi_dmatrix nur mittlere Intensitäten und ist nicht fürs
  215. Dithern geeignet.
  216.  
  217. Die Dichtenberechnung
  218.  
  219. Die Funktion SetDensity muß die Werte der Tags PRTA_LeftBorder, PRTA_TopBorder
  220. und PRTA_MixBWColor anpassen, wenn diese von der Druckdichte abhängig sind.
  221. Dies wird allerdings für die wenigsten Drucker zutreffen. Applikationen sind
  222. jedoch dazu angehalten, diese Werte für jede Druckdichte neu auszulesen.
  223.  
  224. Die Renderfunktion
  225.  
  226. Zwei Fälle der Renderfunktion sind hinzugekommen:
  227.  
  228. Fall 8: Die Funktion wird aufgerufen mit status 8, wenn Farben von RGB
  229. in das Treiberformat umgesetzt werden müssen. Der erste Parameter ct enthält
  230. einen Pointer auf ein Array von Farben. Jeder Eintrag ist so groß, wie
  231. das Tag PRTA_ColorSize angibt oder wie sizeof(union ColorEntry). 
  232. Interpretieren sie die Einträge wie union ColorEntry, so erhalten die Bytes
  233. mit den Indizes PCMRED, PCMGREEN, PCMBLUE die RGB Werte. Der Parameter x
  234. enthält die Anzahl der Einträge im Array. Der Parameter y enthält eine 0, 
  235. falls eine Colormap und 1 falls eine Pixelzeile umgesetzt werden soll.
  236.  
  237. Die Standardumsetzung der RGB Daten in YMCK, wie sie auch das printer.device
  238. benutzt, kann etwa so aussehen:
  239.  
  240. case 8:                  /* Convert RGB source to union ColorEntry */
  241. {
  242.     /*
  243.        ct       - union colorEntry *, pointer to RGB data
  244.        x        - width, number of colors in ct array
  245.        y        - 0: converting colormap, 1: converting pixel row
  246.     */
  247.     union colorEntry *ColorInt = (union colorEntry *) ct;
  248.     LONG width = x;
  249.     ULONG additive = 0xffffffff;
  250.     additive ^= (PD->pd_Preferences.PrintImage == IMAGE_NEGATIVE) ? 0xffffffff : 0;
  251.     if (PD->pd_Preferences.PrintShade == SHADE_COLOR)
  252.     {
  253.         /* we don't need PCMBLACK, so don't calculate it */
  254.         do
  255.         {
  256.             ColorInt->colorLong ^= additive;
  257.             ColorInt++;
  258.         }
  259.         while (--width);
  260.     }
  261.     else
  262.     {
  263.         /* calculate PCMBLACK */
  264.         do
  265.         {
  266.             ColorInt->colorLong ^= additive;
  267.             ColorInt->colorByte[PCMBLACK] =
  268.                 (ColorInt->colorByte[PCMYELLOW]
  269.                 + ColorInt->colorByte[PCMMAGENTA]
  270.                 + ColorInt->colorByte[PCMCYAN]) / 3;
  271.             ColorInt++;
  272.         }
  273.         while (--width);
  274.     }
  275.     break;
  276. }
  277.  
  278. Insbesondere die Berechnung des Grauwertes kann vom einfachen arithmentischen
  279. Mittel der drei Farbintensitäten abweichen.
  280.  
  281.  
  282. Fall 9: Die Funktion wird aufgerufen mit status 9, wenn Farben korrigiert
  283. werden sollen. Der erste Parameter ct enthält einen Pointer auf ein Array
  284. von Farben im Treiberformat (nach render Aufruf 8). Jeder Eintrag ist so groß,
  285. wie das Tag PRTA_ColorSize angibt oder wie sizeof(union ColorEntry).
  286. Der Parameter x enthält die Anzahl der Einträge im Array. Der Parameter y
  287. enthält eine 0, falls eine Colormap und 1 falls eine Pixelzeile korrigiert
  288. werden soll.
  289.  
  290. Die DoSpecial-Funktion
  291.  
  292. Wenn ein Eintrag in der Kommandotabelle "CommandTable" eine "\377" enthält,
  293. so wird die Funktion DoSpecial() aufgerufen. Neu ist: wenn ein Kommando
  294. den String "\377\377" enthält, so werden vor dem Aufruf der Funktion die
  295. I/O Puffer geflusht. Damit kann der Treiber in DoSpecial durch Aufruf
  296. von PWrite, PBothReady und PRead selbst I/O durchführen, ohne eine
  297. Vertauschung des I/O befürchten zu müssen.
  298.  
  299. Das Ergebnis der Funktion wird neu interpretiert, damit DoSpecial auch
  300. allgemeine Druckerfehler zurückgeben kann:
  301.  
  302. Wert         Interpretation
  303.  >0           Anzahl der Zeichen im Puffer
  304.   0           Kommando nicht durch DoSpecial behandelt.
  305.  -1           nicht unterstütztes Kommando
  306.  -2           (neu) Kommando bearbeitet, aber kein Zeichen in den Puffer
  307.                     geschrieben
  308. <-2           (neu) ein I/O oder Druckerfehler minus 65536.
  309.  
  310. Um also einen Fehler von DoSpecial zurückzugeben, ziehen sie vom Fehlercode
  311. einfach 65536 ab.
  312.  
  313.  
  314. 3. Fehlerbehandlung
  315.  
  316. Das neue Feld ped_CallErrHook der Struktur PrinterExtendedData erhält eine
  317. Funktion, die aufgerufen wird, wenn eine Fehlercode des Treibers für die
  318. Ausgabe über einen Hook formatiert werden soll.
  319.  
  320. Der Treiber kann Fehlercodes zwischen PDERR_FIRSTCUSTOM und PDERR_LASTCUSTOM
  321. definieren und aus seinen Funktionen zurückgeben. Wenn die Applikation einen
  322. Hook gesetzt hat um Fehler direkt durch das printer.device auszugeben, so
  323. wird die Funktion ped_CallErrHook für alle Fehlercodes des Treibers 
  324. aufgerufen.
  325.  
  326. Der erste Parameter der Funktion ist ein Pointer auf den I/O Request, der den
  327. Fehler in io_Error enthält. Der zweite Parameter ist der Hook, den die
  328. Applikation gesetzt hat. Der Treiber muß eine Variable vom Typ PrtErrMsg
  329. ausfüllen und dann die Funktion pd_CallErrHook der PrinterData Struktur
  330. aufrufen. Diese erhält als ersten Parameter den Hook, als zweiten Parameter
  331. den I/O Request und als dritten Parameter einen Pointer auf die Variable
  332. des Typs PrtErrMsg.
  333.  
  334. void ErrHook(struct IORequest *ior, struct Hook *hook)
  335. {
  336.     struct EasyStruct es;
  337.     struct PrtErrMsg pem;
  338.     LONG args[2];
  339.     es.es_StructSize = sizeof(es);
  340.     es.es_Flags = 0;
  341.     es.es_Title = NULL;
  342.     es.es_GadgetFormat = "OK";
  343.     pem.pe_Version = PDHOOK_VERSION;
  344.     pem.pe_ErrorLevel = RETURN_FAIL;
  345.     pem.pe_Window = NULL;
  346.     pem.pe_ES = &es;
  347.     pem.pe_IDCMP = NULL;
  348.     pem.pe_ArgList = NULL;
  349.     switch (ior->io_Error)
  350.     {
  351.         case FILEERR_FILEOPENFAILED:
  352.             es.es_TextFormat = "Unable to open file %s.";
  353.             args[0] = (LONG) outfile;
  354.             pem.pe_ArgList = args;
  355.             break;
  356.     }
  357.     PD->pd_CallErrHook(hook,ior,&pem);
  358. }
  359.  
  360. Die Felder es.es_Title und es.es_GadgetFormat können NULL sein, die Funktion
  361. pd_CallErrHook füllt sie passend aus, bevor sie den Hook aufruft.
  362.  
  363.  
  364. 4. Treibereinstellungen
  365.  
  366. Wenn der Treiber eigene Einstellungen unterstützt, so muß er dazu das Tag
  367. PRTA_Preferences auf TRUE setzen und eine Funktion in ped_DoPreferences 
  368. eintragen, die die Einstellungen verwaltet.
  369.  
  370. Treiber können verschiedene Konzepte für Einstellungen unterstützen. Wenn der
  371. Treiber mit hoher Wahrscheinlichkeit durch mehrere Units benutzt wird, so
  372. sollte er für jede Unit eine eigene Einstellungsdatei speichern. Wird er
  373. wahrscheinlich nur von einer Unit benutzt, so reicht eine Einstellungsdatei.
  374. Leitet der Treiber den Namen der Einstellungsdatei dann aus dem Treibernamen
  375. ab, so kann der Benutzer durch Duplizieren des Treibers mit neuem Namen
  376. immerhin auch mehrere Einstellungen verwalten.
  377.  
  378. Eine weitere Entscheidung ist über den Umfang des Einstellerdialogs zu 
  379. treffen. Wenn der Triber sehr umfangreiche Einstellungen zuläßt, so ist es
  380. sinnvoll, wenn der Treiber einen eigenen Einsteller mitbringt (zum Beispiel
  381. PrinterPS), mit dem alle Einstellungen gesetzt werden können. Der Dialog,
  382. der mit Hilfe des Kommandos PRD_EDITPREFS geöffnet wird, sollte dann nur
  383. den Teil der Einstellungen enthalten, der den Ausdruck unmittelbar beeinflußt.
  384.  
  385. Die Funktion ped_DoPreferences wird mit 2 Parametern aufgerufen: ein I/O
  386. Request und ein Kommando. Das Kommando kann 7 verschiedene Fälle angeben:
  387.  
  388. Fall 0: die Einstellungen auf Defaultwerte setzen (PRD_RESETPRFS)
  389.  
  390. Fall 1: die Einstellungen aus einer Datei laden (PRD_LOADPREFS)
  391.  
  392. Fall 2: die Einstellungen in eine Datei in ENV: speichern (PRD_USEPREFS)
  393.  
  394. Fall 3: die Einstellungen in eine Datei in ENV: und in ENVARC: speichern
  395.         (PRD_SAVEPREFS)
  396.  
  397. Fall 4: die Einstellungen in einen I/O Puffer kopieren (PRD_READPREFS)
  398.  
  399. Fall 5: die Einstellungen aus einem I/O Puffer kopieren (PRD_WRITEPREFS)
  400.  
  401. Fall 6: ein Fenster öffnen, in dem die Einstellungen geändert werden können.
  402.         (PRD_EDITPREFS)
  403.  
  404.  
  405. Aufbau der Einstellungsstruktur
  406.  
  407. Die Struktur, in der die Einstellungen gespeichert werden, muß sich von der
  408. Struktur PrtDriverPreferences (Include devices/prtbase.h) ableiten:
  409.  
  410. struct PrtDriverPreferences 
  411. {
  412.     UWORD    pdp_Version;       /* PRIVATE! driver specific version */
  413.     UBYTE    pdp_PrinterID[32]; /* PRIVATE! driver specific id */
  414.     char     pdp_PrefName[FILENAME_SIZE-16];
  415.     ULONG    pdp_Length; /* length of this structure */
  416.     /* more driver private fields follow*/
  417. };
  418.  
  419. Anhand der Version und der PrinterID kann der Treiber seine Einstellungen von
  420. Einstellungen andere Treiber unterscheiden und alte Einstellungen erkennen.
  421.  
  422. Das Array PrefName soll einen lesbaren Namen für die Einstellungen enthalten,
  423. das kann z.B. der Name des Treibers sein.
  424.  
  425. Defaultwerte
  426.  
  427. Viele Programme werden zu Anfang keine Möglichkeit besitzen den 
  428. Einstellungsdialog (Fall 6) aufzurufen. Daher müssen die Defaultwerte wirklich
  429. sinnvoll sein.
  430.  
  431. Einstellungen laden und speichern
  432.  
  433. Die Einstellungen des Treibers werden beim Öffnen einer Unit automatisch 
  434. geladen. Das Dateiformat sollte ein IFF FORM PREF sein und wie die
  435. Systemdateien aufgebaut sein (d.h. ein FORM PRHD und eine eigene FORM für die
  436. Einstellungen selbst enthalten).
  437.  
  438. Einstellungen lesen und schreiben
  439.  
  440. Eine Applikation kann die Einstellungen eines Treibers lesen und für den 
  441. späteren Gebrauch speichern (z.B. um sie über das Schließen der Unit zu
  442. retten). Ebenso kann sie die Einstellungen wieder in den Treiber
  443. zurückschreiben. 
  444.  
  445. case 4:
  446.     /* copy preferences to ior */
  447.     sior = (struct IOStdReq *) ior;
  448.     if (sior->io_Data && sior->io_Offset == 0 && sior->io_Length >= sizeof(DriverPrefs))
  449.     {
  450.         CopyMem(&DriverPrefs,sior->io_Data,sizeof(DriverPrefs));
  451.         sior->io_Actual = sizeof(DriverPrefs);
  452.     }
  453.     else
  454.         error = IOERR_BADLENGTH;
  455.     break;
  456. case 5:
  457.     /* check prefs in ior and copy it to preferences */
  458.     sior = (struct IOStdReq *) ior;
  459.     if (sior->io_Data && sior->io_Offset == 0 && sior->io_Length >= sizeof(struct PrtDriverPreferences))
  460.     {
  461.         tp = (struct FileDriverPrefs *) sior->io_Data;
  462.         /* check prefs data. If this check fails 0 is returned but
  463.            io_Actual is set to 0.
  464.         */
  465.         if (checkDriverPrefs(&tp->fdp_Base))
  466.         {
  467.             CopyMem(tp,&DriverPrefs,sizeof(DriverPrefs));
  468.             sior->io_Actual = sizeof(DriverPrefs);
  469.         }
  470.         else
  471.             sior->io_Actual = 0;
  472.     }
  473.     else
  474.         error = IOERR_BADLENGTH;
  475.     break;
  476.  
  477. Damit der Treiber seine Einstellungen wiedererkennt, muß er den Kopf der
  478. Datenstruktur überprüfen:
  479.  
  480. static int
  481. checkDriverPrefs(struct PrtDriverPreferences *p)
  482. {
  483.     if (p->pdp_Version == 1
  484.         && strcmp(p->pdp_PrinterID,DriverPrefsDefault.fdp_Base.pdp_PrinterID) == 0
  485.         && p->pdp_Length == sizeof(struct FileDriverPrefs))
  486.     {
  487.         return TRUE;
  488.     }
  489.     return FALSE;
  490. }
  491.  
  492. Man beachte, daß im Falle einer nicht erkannten Struktur kein Fehler
  493. zurückgegeben wird, sondern nur io_Actual auf 0 gesetzt wird. Die
  494. Applikation kann also früher gespeicherte Einstellungen (durchaus auch
  495. in einer Datei gespeichert) später wieder zurückschreiben - ein Wechsel
  496. oder Update des Treibers zwischendurch ist dann unproblematisch.
  497.  
  498. Einstellungen editieren
  499.  
  500. Der I/O Request um Einstellungen zu editieren (struct IOPrtPrefsReq)
  501. enthält eine TagListe:
  502.  
  503. PPRA_Window: Der Wert des Tags gibt ein Fenster an. Dieses Fenster legt den
  504. Screen für den Einstellerdialog fest. Das Fenster soll für Eingaben gesperrt
  505. werden, solange der Dialog offen ist.
  506.  
  507. PPRA_Screen: Falls kein Fenster angegeben wird, so kann mit diesem Tag ein
  508. Screen angegeben werden, auf dem sich der Einstellerdialog öffnen soll.
  509.  
  510. PPRA_PubScreen: Der Name eins öffentlichen Screens, auf dem sich der 
  511. Einstellerdialog öffnen soll.
  512.  
  513. Der Einstellerdialog soll nur mit "OK" und "Cancel" beendet werden, d.h. die
  514. Einstellungen werden aus dem Dialog nicht gespeichert. Dafür ist entweder
  515. die Applikation mit PRD_READPREFS/PRD_WRITEPREFS oder ein eigener Einsteller
  516. oder ein Systemprogramm mit PRD_SAVEPREFS zuständig.
  517.  
  518.  
  519. 5. Eigene Farbstruktur
  520.  
  521. Ein Treiber kann eine eigene Farbstruktur benutzen, d.h. er muß nicht die
  522. Standardstruktur union colorEntry benutzen. Das printer.device muß
  523. ausschließlich die Größe der Struktur über PRTA_ColorSize kennen. Natürlich
  524. kann das printer.device dann nur noch wenige Dinge für den Treiber tun: 
  525. Auslesen der Bitmap, dabei werden die Daten in 24 bit RGB gewandelt und 
  526. skalieren der RGB Daten. Alle anderen Aufgaben (Konvertierung vom sRGB 
  527. Farbraum in den druckereigenen Farbraum, Farbkorrektur, Dithering, 
  528. Anti-Alias) muß dann der Treiber übernehmen.
  529.  
  530. Benutzt der Treiber eine von union colorEntry abweichende Farbstruktur, so 
  531. muß er das Tag PRTA_NewColor setzen. Das printer.device setzt damit implizit 
  532. alle Tags, die auf die Druckalgorithmen Einfluß nehmen.
  533.  
  534. Benötigt der Treiber nur einige zusätzliche Bytes in der Farbstruktur, z.B.
  535. für Hilfsdaten während des Rasterns, so kann er mit PRTA_ColorSize die Größe
  536. der neuen Farbstruktur angeben, aber läßt PRTA_NewColor auf dem Wert FALSE.
  537. Die neue Farbstruktur muß dann aber mit union colorEntry beginnen, da das
  538. printer.device die Struktur entsprechend interpretiert:
  539.  
  540. struct LargeColorEntry
  541. {
  542.     union colorEntry lce_ColorEntry;
  543.     LONG lce_Random;
  544. };
  545.